package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.dtos.WmNewsDto;
import com.heima.model.common.dtos.WmNewsPageReqDto;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.common.pojos.wemedia.WmMaterial;
import com.heima.model.common.pojos.wemedia.WmNews;
import com.heima.model.common.pojos.wemedia.WmNewsMaterial;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmTaskService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author Lijx
 * @Date 2024-07-21 19:40
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialMapper newsMaterialMapper;
    @Autowired
    private WmMaterialMapper materialMapper;
    @Autowired
    private WmTaskService wmTaskService;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;


    /**
     * 分页查询文章列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult getPageList(WmNewsPageReqDto dto) {
        //校验参数
        if (dto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.checkParam();

//        LocalDateTime beginPubTime;
//        LocalDateTime endPubTime;
//        if (dto.getBeginPubDate() != null && dto.getEndPubDate() != null) {
//            beginPubTime = LocalDateTime.ofInstant(dto.getBeginPubDate().toInstant(), ZoneId.systemDefault());
//            endPubTime = LocalDateTime.ofInstant(dto.getEndPubDate().toInstant(), ZoneId.systemDefault());
//        }

        //当前登录的用户id
        Integer userId = WmThreadLocalUtil.getUserId();

        //构建查询条件，wrapper
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.<WmNews>lambdaQuery().eq(dto.getChannelId() != null, WmNews::getChannelId, dto.getChannelId())
                .eq(userId != null,WmNews::getUserId,userId)
                .eq(dto.getStatus() != null, WmNews::getStatus, dto.getStatus())
                .like(dto.getKeyword() != null, WmNews::getTitle, dto.getKeyword())
                .between(dto.getBeginPubDate() != null && dto.getEndPubDate() != null, WmNews::getPublishTime, dto.getBeginPubDate(), dto.getEndPubDate())
                .orderByDesc(WmNews::getPublishTime);


        //构建page
        Page<WmNews> page = new Page<>(dto.getPage(), dto.getSize());

        //查询数据
        page(page,wrapper);

        //封装数据返回
        PageResponseResult pageResponseResult = new PageResponseResult(
                (int) page.getCurrent(),
                (int) page.getSize(),
                (int) page.getTotal());
        pageResponseResult.setData(page.getRecords());
        return pageResponseResult;
    }

    /**
     * 文章发布
     * @param newsDto
     * @return
     */
    @Override
    public ResponseResult submitNews(WmNewsDto newsDto) {
        //参数校验
        if (newsDto == null || StringUtils.isEmpty(newsDto.getTitle()) || StringUtils.isEmpty(newsDto.getContent())) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        
        //1.1 拷贝数据到文章实体类wmNews中
        WmNews news = new WmNews();
        BeanUtils.copyProperties(newsDto,news);
        //1.2 处理文章封面图片type数据
        if (newsDto.getType() == -1) {
            news.setType(null);
        }
        //1.3 处理封面图片image数据
        if (newsDto.getImages() != null && newsDto.getImages().size()>0) {
            String images = StringUtils.join(newsDto.getImages(), ",");
            news.setImages(images);
        }
        //1.4 封装用户id
        Integer userId = WmThreadLocalUtil.getUserId();
        if (userId == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        news.setUserId(userId);

        //新增或修改文章：wm_news
        insertOrUpdate(news);
        
        //判断本次操作是否为草稿：草稿则结束本次流程
        if (news.getStatus() == 0) {
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }

        //文章与素材的关联关系表：:wm_news_material
        //3.提取文章内容中的素材图片，并维护内容图片与素材表的关联关系
        List<String> images = getImagesInContent(news.getContent());
        saveRelationWithContentImage(images,news);

        //4.维护封面图片与素材表的关联关系
        saveRelationWithCoverImage(images,newsDto,news);

        //5. 异步调用添加任务功能：添加一个审核文章的任务
        wmTaskService.addTask(news);

//        //5. 开启自动审核发布文章
//        autoScanService.autoScan(news.getId());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 查询文章详情
     * @param id
     * @return
     */
    @Override
    public ResponseResult selectNewsDetail(Integer id) {
        if (id == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //查询文章信息
        WmNews news = getOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, id));

        if (news == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        return ResponseResult.okResult(news);
    }

    /**
     * 删除文章
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult deleteNewsById(Integer id) {
        if (id == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }

        //查询文章信息
        WmNews news = getById(id);

        if (news == null) {
            //文章不存在
            return ResponseResult.errorResult(501,"文章不存在");
        }
        //判断文章是否发布
        if (news.getStatus() == 9) { //9表示已经发布

            return ResponseResult.errorResult(501,"文章已经发布，不能删除");
        }

        //根据文章id删除文章素材关联表
        newsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,id));
        //删除文章信息
        removeById(id);
        //逻辑删除app端文章


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 修改文章上下架
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto newsDto) {
        if (newsDto == null || newsDto.getId() == null || newsDto.getEnable() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }

        //查询文章信息
        WmNews news = getById(newsDto.getId());
        if (news == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //判断文章状态是否发布
        if (news.getStatus() != 9 ) {
            return ResponseResult.errorResult(501,"当前文章不是发布状态，不能上下架");
        }

        //修改文章状态
        news.setEnable(newsDto.getEnable());
        updateById(news);

        //发送消息到kafka，通知article微服务经行app文章的上下架操作
        Map<String,Object> params = new HashMap<>();
        params.put("articleId",news.getArticleId());
        params.put("enable",news.getEnable()); //1:上架，0:下架
        //发送消息
        kafkaTemplate.send("article_up_or_down", JSON.toJSONString(params));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 第一个功能：如果当前封面类型为自动，则设置封面类型的数据
     * 匹配规则：
     *      1，如果内容图片大于等于1，小于3  单图  type 1
     *      2，如果内容图片大于等于3  多图  type 3
     *      3，如果内容没有图片，无图  type 0
     *
     * 第二个功能：保存封面图片与素材的关系
     *
     * @param contentImages
     * @param newsDto
     * @param news
     */
    private void saveRelationWithCoverImage(List<String> contentImages, WmNewsDto newsDto, WmNews news) {
        //获取文章封面图片集合
        List<String> images = newsDto.getImages();

        //判断封面类型是否是自动：type为-1
        if (newsDto.getType() == -1) {
            if (contentImages != null && contentImages.size() >=1 && contentImages.size()<3) {
                images = contentImages.stream().limit(1).collect(Collectors.toList());
                //单图
                news.setType((short)1);
            }else if (contentImages != null && contentImages.size() >=3){
                images = contentImages.stream().limit(3).collect(Collectors.toList());
                //三图
                news.setType((short)3);
            }else if (contentImages == null || contentImages.size() ==0){
                news.setType((short)0);
            }

            if (images != null && images.size() >0) {
                String urls = StringUtils.join(images, ",");
                news.setImages(urls);
            }
            //修改文章信息
            updateById(news);
        }

        //保存封面图片与素材的关系
        if (images != null && images.size() >0) {
            saveRelationWithImg(contentImages,news,1); //1表示文章封面引用图片
        }
    }

    /**
     * 维护内容图片与素材表的关联关系
     */
    private void saveRelationWithContentImage(List<String> imnages, WmNews news) {
        //保存内容图片与素材表的关联关系
        saveRelationWithImg(imnages,news,0); //0表示文章内容引用图片
    }

    /**
     * 保存图片与素材表的关联关系
     * @param imnages
     * @param news
     * @param type
     */
    private void saveRelationWithImg(List<String> imnages, WmNews news, int type) {

        if (imnages != null && imnages.size() >0) {
            //查询素材表
            List<WmMaterial> wmMaterials = materialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, imnages));
            //获取图片素材id
            List<Integer> materialIds = wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());
            //保存图片与素材表的关联关系
            newsMaterialMapper.saveRelations(materialIds,news.getId(),(short)type);
        }
    }

    /**
     * 提取文章内容中的素材图片
     * @param content
     * @return
     */
    private List<String> getImagesInContent(String content) {
        List<Map> maps = JSONArray.parseArray(content, Map.class);
        List<String> urls = new ArrayList<>();
        for (Map map : maps) {
            String type = map.get("type").toString();
            //判断是否是图片
            if ("image".equals(type)) {
                String url = map.get("value").toString();
                urls.add(url);
            }
        }
        return urls;
    }

    /**
     * 新增或修改文章
     * @param news
     */
    private void insertOrUpdate(WmNews news) {
        //如果是新增保存文章：则文章id为空
        if (news.getId() == null) {
            //1、新增保存文章
            //给的创建时间
            news.setCreatedTime(new Date());
            //默认上架
            news.setEnable((short)1);

            save(news);
        }else {
            //2、修改文章信息
            //2.1、删除文章素材管理表的数据
            newsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,news.getId()));
            //2.2、修改文章数据
            updateById(news);
        }
    }
}
